Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/rnsh_manager.py c0b0ddffd735a0d007c1be9a5e8563ec42fdafc0 (c0b0ddff) Text, 32.11 KB

T8b949e# SPDX-License-Identifier: 0BSD

T8b949e"""RNSh session manager for MeshChatX.

Tracks multiple rnsh subprocess sessions, keeps them running in the background
while the app is active, and persists session definitions plus output history.
"""

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations

Tff7b72import T7ee787contextlib
Tff7b72import T7ee787importlibT7ee787.T7ee787util
Tff7b72import T7ee787json
Tff7b72import T7ee787os
Tff7b72import T7ee787re
Tff7b72import T7ee787shlex
Tff7b72import T7ee787shutil
Tff7b72import T7ee787struct
Tff7b72import T7ee787subprocess
Tff7b72import T7ee787sys
Tff7b72import T7ee787threading
Tff7b72import T7ee787time
Tff7b72import T7ee787uuid
Tff7b72from T7ee787collections Tff7b72import Te6edf3deque

Tff7b72tryTb4b4b4:
Tff7b72import T7ee787fcntl
Tff7b72import T7ee787pty
Tff7b72import T7ee787termios
Tff7b72except Tf85149ImportErrorTb4b4b4: T8b949e# pragma: no cover - non-POSIX platforms
Te6edf3fcntl Tff7b72= Tff7b72None
Te6edf3pty Tff7b72= Tff7b72None
Te6edf3termios Tff7b72= Tff7b72None

Te6edf3_PTY_SUPPORTED Tff7b72= Te6edf3osTff7b72.Td2a8ffname Tff7b72== Ta5d6ff"Ta5d6ffposixTa5d6ff" Tff7b72and Te6edf3pty Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3termios Tff7b72is Tff7b72not Tff7b72None

T8b949e# Default pseudo-terminal geometry used until the client reports a real size.
Te6edf3DEFAULT_TERMINAL_ROWS Tff7b72= T79c0ff40
Te6edf3DEFAULT_TERMINAL_COLS Tff7b72= T79c0ff120

T8b949e# Matches the listener address that rnsh logs on startup, e.g.
T8b949e# "rnsh listening for commands on <a1b2c3...>" or "Listening on : <...>".
T8b949e# Require the listening phrase so verbose identity/transport hashes are ignored.
Te6edf3_LISTEN_ADDRESS_RE Tff7b72= Te6edf3reTff7b72.Td2a8ffcompileTb4b4b4(
Ta5d6ffrTa5d6ff"Ta5d6fflistening(?:Ta5d6ff\Ta5d6ffs+forTa5d6ff\Ta5d6ffs+commands)?Ta5d6ff\Ta5d6ffs+onTa5d6ff\Ta5d6ffs*:?Ta5d6ff\Ta5d6ffs*<([0-9a-fA-F]Ta5d6ff{Ta5d6ff16,})>Ta5d6ff"Tb4b4b4,
Te6edf3reTff7b72.Td2a8ffIGNORECASETb4b4b4,
Tb4b4b4)

Te6edf3_RNSH_MODULE Tff7b72= Ta5d6ff"Ta5d6ffRNS.Utilities.rnsh.rnshTa5d6ff"
T8b949e# cx_Freeze / AppImage bundles set sys.executable to MeshChatX itself, which
T8b949e# does not accept Python's -m. meshchat.main() dispatches this flag to
T8b949e# runpy.run_module before argparse (see meshchatx/meshchat.py).
Te6edf3_MESHCHATX_RUN_MODULE_FLAG Tff7b72= Ta5d6ff"Ta5d6ff--meshchatx-run-moduleTa5d6ff"


Tff7b72class T56d364RNSHSessionTb4b4b4:
T8b949e"""Runtime state for a single rnsh session."""

Te6edf3STATUS_STOPPED Tff7b72= Ta5d6ff"Ta5d6ffstoppedTa5d6ff"
Te6edf3STATUS_RUNNING Tff7b72= Ta5d6ff"Ta5d6ffrunningTa5d6ff"
Te6edf3STATUS_FAILED Tff7b72= Ta5d6ff"Ta5d6fffailedTa5d6ff"

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3managerTb4b4b4, Te6edf3session_idTb4b4b4, Te6edf3configTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmanager Tff7b72= Te6edf3manager
Tff7b72selfTff7b72.Td2a8ffsession_id Tff7b72= Te6edf3session_id
Tff7b72selfTff7b72.Td2a8ffconfig Tff7b72= Tffa657dictTb4b4b4(Te6edf3config Tff7b72or Tb4b4b4{Tb4b4b4}Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcreated_at Tff7b72= Tffa657floatTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Tffa657floatTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4) Tff7b72or Tff7b72selfTff7b72.Td2a8ffcreated_atTb4b4b4)

Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tffa657strTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4) Tff7b72or Tff7b72selfTff7b72.Td2a8ffSTATUS_STOPPEDTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffpid Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflast_exit_code Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_exit_codeTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_errorTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflast_command Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_commandTa5d6ff"Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_process Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_master_fd Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_stop_requested Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_output_seq Tff7b72= Tffa657intTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffoutput_seqTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_output_chunks Tff7b72= Te6edf3dequeTb4b4b4(Te6edf3maxlenTff7b72=T79c0ff4000Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_output_text Tff7b72= Ta5d6ff"Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ff_lock Tff7b72= Te6edf3threadingTff7b72.Td2a8ffRLockTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_last_persist Tff7b72= T79c0ff0.0

Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_rows Tff7b72= Tffa657maxTb4b4b4(T79c0ff1Tb4b4b4, Tffa657intTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffrowsTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3DEFAULT_TERMINAL_ROWSTb4b4b4)Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_rows Tff7b72= Te6edf3DEFAULT_TERMINAL_ROWS
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_cols Tff7b72= Tffa657maxTb4b4b4(T79c0ff1Tb4b4b4, Tffa657intTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcolsTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3DEFAULT_TERMINAL_COLSTb4b4b4)Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_cols Tff7b72= Te6edf3DEFAULT_TERMINAL_COLS

Te6edf3stored_address Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflisten_addressTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflisten_address Tff7b72= Tb4b4b4(
Te6edf3stored_addressTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3stored_addressTb4b4b4, Tffa657strTb4b4b4) Tff7b72else Ta5d6ff"Ta5d6ff"
Tb4b4b4)

Te6edf3saved_output Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffoutput_chunksTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3saved_outputTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3item Tff7b72in Te6edf3saved_outputTb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3seq Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4)
Te6edf3text Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4)
Te6edf3ts Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftsTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3seqTb4b4b4, Tffa657intTb4b4b4) Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3textTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_output_chunksTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4: Te6edf3seqTb4b4b4,
Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4: Te6edf3textTb4b4b4,
Ta5d6ff"Ta5d6fftsTa5d6ff"Tb4b4b4: Tffa657floatTb4b4b4(Te6edf3tsTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3tsTb4b4b4, Tb4b4b4(Tffa657intTb4b4b4, Tffa657floatTb4b4b4)Tb4b4b4)
Tff7b72else Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_output_chunksTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_output_seq Tff7b72= Tffa657maxTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_output_seqTb4b4b4, Tff7b72selfTff7b72.Td2a8ff_output_chunksTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_output_text Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(
Te6edf3chunkTb4b4b4[Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4] Tff7b72for Te6edf3chunk Tff7b72in Tff7b72selfTff7b72.Td2a8ff_output_chunks
Tb4b4b4)

Tf0883e@property
Tff7b72def Td2a8ffnameTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3configured Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3configuredTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Te6edf3configuredTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3configuredTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Te6edf3mode Tff7b72= Tff7b72selfTff7b72.Td2a8ffmode
Tff7b72if Te6edf3mode Tff7b72== Ta5d6ff"Ta5d6fflistenTa5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffListenerTa5d6ff"
Te6edf3destination Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestination
Tff7b72if Te6edf3destinationTb4b4b4:
Tff7b72return Ta5d6fffTa5d6ff"Ta5d6ffSession Tffd700{Te6edf3destinationTb4b4b4[Tb4b4b4:T79c0ff10Tb4b4b4]Tffd700}Ta5d6ff"
Tff7b72return Ta5d6ff"Ta5d6ffSessionTa5d6ff"

Tf0883e@property
Tff7b72def Td2a8ffmodeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3mode Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3mode Tff7b72== Ta5d6ff"Ta5d6fflistenTa5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6fflistenTa5d6ff"
Tff7b72return Ta5d6ff"Ta5d6ffconnectTa5d6ff"

Tf0883e@property
Tff7b72def Td2a8ffdestinationTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3value Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdestinationTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3valueTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72return Ta5d6ff"Ta5d6ff"

Tf0883e@property
Tff7b72def Td2a8ffresolved_config_dirTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""The Reticulum config directory rnsh is launched against.

A per-session config_path override wins; otherwise the manager's
shared directory (the MeshChatX app's Reticulum instance) is used so
rnsh attaches to the same shared instance.
"""
Te6edf3configured Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffconfig_pathTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3configuredTb4b4b4:
Tff7b72return Te6edf3configured
Te6edf3manager_config_dir Tff7b72= Tffa657getattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmanagerTb4b4b4, Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3manager_config_dirTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3manager_config_dirTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72return Ta5d6ff"Ta5d6ff"

Tff7b72def Td2a8ffto_dictTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3include_output_tailTff7b72=Tff7b72FalseTb4b4b4, Te6edf3output_tail_sizeTff7b72=T79c0ff120Tb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3payload Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffsession_idTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffnameTb4b4b4,
Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffmodeTb4b4b4,
Ta5d6ff"Ta5d6ffdestinationTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffdestinationTb4b4b4,
Ta5d6ff"Ta5d6ffconfig_dirTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffresolved_config_dirTb4b4b4,
Ta5d6ff"Ta5d6fflisten_addressTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflisten_addressTb4b4b4,
Ta5d6ff"Ta5d6ffrowsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_rowsTb4b4b4,
Ta5d6ff"Ta5d6ffcolsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_colsTb4b4b4,
Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4: Tffa657dictTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffstatusTb4b4b4,
Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffpidTb4b4b4,
Ta5d6ff"Ta5d6fflast_exit_codeTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflast_exit_codeTb4b4b4,
Ta5d6ff"Ta5d6fflast_errorTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflast_errorTb4b4b4,
Ta5d6ff"Ta5d6fflast_commandTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflast_commandTb4b4b4,
Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffcreated_atTb4b4b4,
Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffupdated_atTb4b4b4,
Ta5d6ff"Ta5d6ffoutput_seqTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_output_seqTb4b4b4,
Ta5d6ff"Ta5d6ffoutput_sizeTa5d6ff"Tb4b4b4: Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_output_chunksTb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72if Te6edf3include_output_tailTb4b4b4:
Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffoutput_chunksTa5d6ff"Tb4b4b4] Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_output_chunksTb4b4b4)Tb4b4b4[
Tff7b72-Tffa657maxTb4b4b4(T79c0ff1Tb4b4b4, Tffa657intTb4b4b4(Te6edf3output_tail_sizeTb4b4b4)Tb4b4b4) Tb4b4b4:
Tb4b4b4]
Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffoutput_textTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ff_output_textTb4b4b4[Tff7b72-T79c0ff50000Tb4b4b4:Tb4b4b4]
Tff7b72return Te6edf3payload

Tff7b72def Td2a8ffoutput_sinceTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3cursorTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3chunks Tff7b72= Tb4b4b4[Te6edf3chunk Tff7b72for Te6edf3chunk Tff7b72in Tff7b72selfTff7b72.Td2a8ff_output_chunks Tff7b72if Te6edf3chunkTb4b4b4[Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4] Tff7b72> Te6edf3cursorTb4b4b4]
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffchunksTa5d6ff"Tb4b4b4: Te6edf3chunksTb4b4b4,
Ta5d6ff"Ta5d6ffnext_cursorTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_output_seqTb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ffclear_outputTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_output_chunksTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_output_text Tff7b72= Ta5d6ff"Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ff_output_seq Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ff_on_session_changeTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffappend_outputTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3textTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3textTb4b4b4, Tffa657strTb4b4b4) Tff7b72or Tff7b72not Te6edf3textTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3listen_address_changed Tff7b72= Tff7b72False
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_output_seq Tff7b72+Tff7b72= T79c0ff1
Te6edf3chunk Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_output_seqTb4b4b4,
Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4: Te6edf3textTb4b4b4,
Ta5d6ff"Ta5d6fftsTa5d6ff"Tb4b4b4: Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_output_chunksTff7b72.Td2a8ffappendTb4b4b4(Te6edf3chunkTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_output_text Tff7b72+Tff7b72= Te6edf3text
Tff7b72if Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_output_textTb4b4b4) Tff7b72> T79c0ff200000Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_output_text Tff7b72= Tff7b72selfTff7b72.Td2a8ff_output_textTb4b4b4[Tff7b72-T79c0ff200000Tb4b4b4:Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3chunkTb4b4b4[Ta5d6ff"Ta5d6fftsTa5d6ff"Tb4b4b4]
Te6edf3listen_address_changed Tff7b72= Tff7b72selfTff7b72.Td2a8ff_maybe_detect_listen_addressTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3listen_address_changedTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ff_on_session_changeTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72return Te6edf3chunk

Tff7b72def Td2a8ff_maybe_detect_listen_addressTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Extract the listener destination hash from rnsh log output.

Must be called while holding self._lock.
Returns True when a new listen address was stored.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffmode Tff7b72!= Ta5d6ff"Ta5d6fflistenTa5d6ff" Tff7b72or Tff7b72selfTff7b72.Td2a8fflisten_addressTb4b4b4:
Tff7b72return Tff7b72False
Te6edf3tail Tff7b72= Tff7b72selfTff7b72.Td2a8ff_output_textTb4b4b4[Tff7b72-T79c0ff4000Tb4b4b4:Tb4b4b4]
Te6edf3match Tff7b72= Te6edf3_LISTEN_ADDRESS_RETff7b72.Td2a8ffsearchTb4b4b4(Te6edf3tailTb4b4b4)
Tff7b72if Te6edf3matchTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflisten_address Tff7b72= Te6edf3matchTff7b72.Td2a8ffgroupTb4b4b4(T79c0ff1Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72return Tff7b72False

Tf0883e@staticmethod
Tff7b72def Td2a8ff_rnsh_module_availableTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72return Te6edf3importlibTff7b72.Td2a8ffutilTff7b72.Td2a8fffind_specTb4b4b4(Te6edf3_RNSH_MODULETb4b4b4) Tff7b72is Tff7b72not Tff7b72None
Tff7b72except Tb4b4b4(Tf85149ImportErrorTb4b4b4, Tf85149ModuleNotFoundErrorTb4b4b4, Tf85149ValueErrorTb4b4b4, Tf85149AttributeErrorTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False

Tf0883e@staticmethod
Tff7b72def Td2a8ff_is_frozen_executableTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tffa657boolTb4b4b4(Tffa657getattrTb4b4b4(Te6edf3sysTb4b4b4, Ta5d6ff"Ta5d6fffrozenTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ff_resolve_rnsh_launcherTb4b4b4(Tb4b4b4)Tb4b4b4:
T8b949e"""Return argv prefix for launching rnsh.

Prefer the Python module entry point so sessions work when the PATH
console-script wrapper is not executable (common with pip --user
installs) or when Landlock denies executing paths outside allowed
read roots (for example ~/.local/bin/rnsh).

Frozen desktop builds (Windows EXE, AppImage, macOS) set
sys.executable to MeshChatX itself, which rejects -m. Those
builds re-enter via --meshchatx-run-module instead.
"""
Tff7b72if Te6edf3RNSHSessionTff7b72.Td2a8ff_rnsh_module_availableTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3RNSHSessionTff7b72.Td2a8ff_is_frozen_executableTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Te6edf3_MESHCHATX_RUN_MODULE_FLAGTb4b4b4,
Te6edf3_RNSH_MODULETb4b4b4,
Tb4b4b4]
Tff7b72return Tb4b4b4[Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4, Ta5d6ff"Ta5d6ff-mTa5d6ff"Tb4b4b4, Te6edf3_RNSH_MODULETb4b4b4]
Te6edf3executable Tff7b72= Te6edf3shutilTff7b72.Td2a8ffwhichTb4b4b4(Ta5d6ff"Ta5d6ffrnshTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3executable Tff7b72and Te6edf3osTff7b72.Td2a8ffaccessTb4b4b4(Te6edf3executableTb4b4b4, Te6edf3osTff7b72.Td2a8ffX_OKTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Te6edf3executableTb4b4b4]
Tff7b72if Te6edf3executableTb4b4b4:
Tff7b72raise Tf85149PermissionErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffPermission denied: Ta5d6ff'Tffd700{Te6edf3executableTffd700}Ta5d6ff'Ta5d6ff"Tb4b4b4)
Tff7b72raise Tf85149FileNotFoundErrorTb4b4b4(
Ta5d6ff"Ta5d6ffrnsh is not available; install the rns package or ensure rnsh is on PATHTa5d6ff"Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ff_build_commandTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3command Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_resolve_rnsh_launcherTb4b4b4(Tb4b4b4)Tb4b4b4)

T8b949e# Attach rnsh to the same Reticulum config directory (and therefore the
T8b949e# same shared instance and rpc_key) as the MeshChatX app. Without this
T8b949e# rnsh bootstraps its own default config, becomes a mismatched shared
T8b949e# instance client and fails RPC auth with "digest sent was rejected".
T8b949e# RNS 1.4.0+: --rnsconfig is the Reticulum config dir. -c/--config is
T8b949e# the rnsh config directory (HOME/.rnsh via _build_env).
Te6edf3config_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffresolved_config_dir
Tff7b72if Te6edf3config_pathTb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff--rnsconfigTa5d6ff"Tb4b4b4, Te6edf3config_pathTb4b4b4]Tb4b4b4)

Te6edf3identity_path Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidentity_pathTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3identity_pathTb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-iTa5d6ff"Tb4b4b4, Te6edf3identity_pathTb4b4b4]Tb4b4b4)

Te6edf3verbose Tff7b72= Tffa657intTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffverboseTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Te6edf3quiet Tff7b72= Tffa657intTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffquietTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Tff7b72if Te6edf3verbose Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-vTa5d6ff"Tb4b4b4] Tff7b72* Tffa657minTb4b4b4(Te6edf3verboseTb4b4b4, T79c0ff3Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3quiet Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-qTa5d6ff"Tb4b4b4] Tff7b72* Tffa657minTb4b4b4(Te6edf3quietTb4b4b4, T79c0ff3Tb4b4b4)Tb4b4b4)

Tff7b72if Tffa657boolTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffmirrorTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff-mTa5d6ff"Tb4b4b4)

Te6edf3timeout Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftimeoutTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3timeout Tff7b72not Tff7b72in Tb4b4b4(Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-wTa5d6ff"Tb4b4b4, Tffa657strTb4b4b4(Te6edf3timeoutTb4b4b4)Tb4b4b4]Tb4b4b4)

Te6edf3service Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffserviceTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3serviceTb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-sTa5d6ff"Tb4b4b4, Te6edf3serviceTb4b4b4]Tb4b4b4)

Te6edf3extra_args Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffextra_argsTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3extra_argsTb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Te6edf3shlexTff7b72.Td2a8ffsplitTb4b4b4(Te6edf3extra_argsTb4b4b4)Tb4b4b4)

Te6edf3mode Tff7b72= Tff7b72selfTff7b72.Td2a8ffmode
Tff7b72if Te6edf3mode Tff7b72== Ta5d6ff"Ta5d6fflistenTa5d6ff"Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff-lTa5d6ff"Tb4b4b4)

Te6edf3announce_period Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffannounce_periodTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3announce_period Tff7b72not Tff7b72in Tb4b4b4(Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-bTa5d6ff"Tb4b4b4, Tffa657strTb4b4b4(Te6edf3announce_periodTb4b4b4)Tb4b4b4]Tb4b4b4)

Te6edf3allowed_hashes Tff7b72= Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffallowed_hashesTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3allowed_hashesTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3item Tff7b72in Te6edf3allowed_hashesTb4b4b4:
Te6edf3value Tff7b72= Tffa657strTb4b4b4(Te6edf3itemTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3valueTb4b4b4:
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Tb4b4b4[Ta5d6ff"Ta5d6ff-aTa5d6ff"Tb4b4b4, Te6edf3valueTb4b4b4]Tb4b4b4)

Tff7b72if Tffa657boolTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffno_authTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff-nTa5d6ff"Tb4b4b4)

Tff7b72if Tffa657boolTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffremote_command_as_argsTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff-ATa5d6ff"Tb4b4b4)

Tff7b72if Tffa657boolTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffno_remote_commandTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff-CTa5d6ff"Tb4b4b4)

Te6edf3default_command Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdefault_commandTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3default_commandTb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff--Ta5d6ff"Tb4b4b4)
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Te6edf3shlexTff7b72.Td2a8ffsplitTb4b4b4(Te6edf3default_commandTb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72if Tffa657boolTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffno_idTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff-NTa5d6ff"Tb4b4b4)

Te6edf3destination Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestination
Tff7b72if Tff7b72not Te6edf3destinationTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffDestination hash is required for connect modeTa5d6ff"Tb4b4b4)
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Te6edf3destinationTb4b4b4)

Te6edf3remote_command Tff7b72= Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffremote_commandTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3remote_commandTb4b4b4:
Te6edf3commandTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ff--Ta5d6ff"Tb4b4b4)
Te6edf3commandTff7b72.Td2a8ffextendTb4b4b4(Te6edf3shlexTff7b72.Td2a8ffsplitTb4b4b4(Te6edf3remote_commandTb4b4b4)Tb4b4b4)

Tff7b72return Te6edf3command

Tf0883e@staticmethod
Tff7b72def Td2a8ff_supports_ptyTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_PTY_SUPPORTED

Tff7b72def Td2a8ff_resolved_rnsh_homeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Directory used as HOME for the rnsh subprocess.

Upstream rnsh always creates or opens ~/.rnsh (see ensure_config_directory).
Under Landlock the real home is not writable, so MeshChatX points HOME at
an identity-scoped path under storage that the sandbox already allows.
"""
Te6edf3storage Tff7b72= Tffa657getattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmanagerTb4b4b4, Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3storageTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Te6edf3storageTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storageTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffrnsh_homeTa5d6ff"Tb4b4b4)
Tff7b72return Ta5d6ff"Ta5d6ff"

Tff7b72def Td2a8ff_ensure_rnsh_homeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3home_dirTb4b4b4)Tb4b4b4:
T8b949e"""Create HOME and the ~/.rnsh layout rnsh expects before spawn."""
Tff7b72if Tff7b72not Te6edf3home_dirTb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ff"
Te6edf3rnsh_cfg Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3home_dirTb4b4b4, Ta5d6ff"Ta5d6ff.rnshTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3rnsh_cfgTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72return Te6edf3home_dir

Tff7b72def Td2a8ff_build_envTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3env Tff7b72= Tffa657dictTb4b4b4(Te6edf3osTff7b72.Td2a8ffenvironTb4b4b4)
Te6edf3envTff7b72.Td2a8ffsetdefaultTb4b4b4(Ta5d6ff"Ta5d6ffTERMTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffxterm-256colorTa5d6ff"Tb4b4b4)
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffCOLUMNSTa5d6ff"Tb4b4b4] Tff7b72= Tffa657strTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_colsTb4b4b4)
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffLINESTa5d6ff"Tb4b4b4] Tff7b72= Tffa657strTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_rowsTb4b4b4)
T8b949e# Pipe mode (Windows and pytest) has no TTY, so CPython fully buffers
T8b949e# stdout and listen-address lines never reach the reader promptly.
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffPYTHONUNBUFFEREDTa5d6ff"Tb4b4b4] Tff7b72= Ta5d6ff"Ta5d6ff1Ta5d6ff"
Te6edf3home_dir Tff7b72= Tff7b72selfTff7b72.Td2a8ff_ensure_rnsh_homeTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_resolved_rnsh_homeTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3home_dirTb4b4b4:
T8b949e# Keep rnsh's ensure_config_directory() inside the Landlock RW tree.
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffHOMETa5d6ff"Tb4b4b4] Tff7b72= Te6edf3home_dir
T8b949e# Avoid picking up a host XDG tree that Landlock cannot create under.
Te6edf3envTff7b72.Td2a8ffpopTb4b4b4(Ta5d6ff"Ta5d6ffXDG_CONFIG_HOMETa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72return Te6edf3env

Tf0883e@staticmethod
Tff7b72def Td2a8ff_set_winsizeTb4b4b4(Te6edf3fdTb4b4b4, Te6edf3rowsTb4b4b4, Te6edf3colsTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3fcntl Tff7b72is Tff7b72None Tff7b72or Te6edf3termios Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3winsize Tff7b72= Te6edf3structTff7b72.Td2a8ffpackTb4b4b4(Ta5d6ff"Ta5d6ffHHHHTa5d6ff"Tb4b4b4, Tffa657intTb4b4b4(Te6edf3rowsTb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Te6edf3colsTb4b4b4)Tb4b4b4, T79c0ff0Tb4b4b4, T79c0ff0Tb4b4b4)
Te6edf3fcntlTff7b72.Td2a8ffioctlTb4b4b4(Te6edf3fdTb4b4b4, Te6edf3termiosTff7b72.Td2a8ffTIOCSWINSZTb4b4b4, Te6edf3winsizeTb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ff_acquire_controlling_ttyTb4b4b4(Tb4b4b4)Tb4b4b4: T8b949e# pragma: no cover - runs in child process
T8b949e"""Make the slave pty the controlling terminal of the child.

Runs in the forked child after start_new_session has called
setsid and after stdio has been redirected to the slave pty.
"""
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3fcntlTff7b72.Td2a8ffioctlTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3termiosTff7b72.Td2a8ffTIOCSCTTYTb4b4b4, T79c0ff0Tb4b4b4)

Tff7b72def Td2a8ffstartTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3notify_failure Tff7b72= Tff7b72False
Te6edf3failure Tff7b72= Tff7b72None
Te6edf3started_process Tff7b72= Tff7b72None
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_process Tff7b72is Tff7b72not Tff7b72None Tff7b72and Tff7b72selfTff7b72.Td2a8ff_processTff7b72.Td2a8ffpollTb4b4b4(Tb4b4b4) Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3command Tff7b72= Tff7b72selfTff7b72.Td2a8ff_build_commandTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTATUS_FAILED
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tffa657strTb4b4b4(Te6edf3excTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffpid Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3notify_failure Tff7b72= Tff7b72True
Te6edf3failure Tff7b72= Te6edf3exc
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_stop_requested Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8fflast_exit_code Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8fflast_command Tff7b72= Ta5d6ff"Ta5d6ff Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3shlexTff7b72.Td2a8ffquoteTb4b4b4(Te6edf3partTb4b4b4) Tff7b72for Te6edf3part Tff7b72in Te6edf3commandTb4b4b4)

Te6edf3notify_failure Tff7b72= Tff7b72False
Te6edf3failureTb4b4b4: Tf85149Exception Tff7b72| Tff7b72None Tff7b72= Tff7b72None

Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_supports_ptyTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_start_with_ptyTb4b4b4(Te6edf3commandTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_start_with_pipeTb4b4b4(Te6edf3commandTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTATUS_FAILED
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tffa657strTb4b4b4(Te6edf3excTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffpid Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_process Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_master_fd Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3notify_failure Tff7b72= Tff7b72True
Te6edf3failure Tff7b72= Te6edf3exc
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpid Tff7b72= Tff7b72selfTff7b72.Td2a8ff_processTff7b72.Td2a8ffpid
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTATUS_RUNNING
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3started_process Tff7b72= Tff7b72selfTff7b72.Td2a8ff_process

Tff7b72if Te6edf3notify_failureTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ff_on_session_changeTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3failure Tff7b72is Tff7b72not Tff7b72None
Tff7b72raise Te6edf3failure

Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ff_on_session_changeTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)

Te6edf3reader Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ff_reader_loopTb4b4b4, Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3readerTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)

Te6edf3waiter Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(
Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ff_waiter_loopTb4b4b4,
Te6edf3argsTff7b72=Tb4b4b4(Te6edf3started_processTb4b4b4,Tb4b4b4)Tb4b4b4,
Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)
Te6edf3waiterTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)

Tff7b72return Tff7b72selfTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72def Td2a8ff_start_with_ptyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3commandTb4b4b4)Tb4b4b4:
Te6edf3master_fdTb4b4b4, Te6edf3slave_fd Tff7b72= Te6edf3ptyTff7b72.Td2a8ffopenptyTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_set_winsizeTb4b4b4(Te6edf3master_fdTb4b4b4, Tff7b72selfTff7b72.Td2a8ff_rowsTb4b4b4, Tff7b72selfTff7b72.Td2a8ff_colsTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_process Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffPopenTb4b4b4( T8b949e# noqa: S603
Te6edf3commandTb4b4b4,
Te6edf3stdinTff7b72=Te6edf3slave_fdTb4b4b4,
Te6edf3stdoutTff7b72=Te6edf3slave_fdTb4b4b4,
Te6edf3stderrTff7b72=Te6edf3slave_fdTb4b4b4,
Te6edf3start_new_sessionTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3preexec_fnTff7b72=Tff7b72selfTff7b72.Td2a8ff_acquire_controlling_ttyTb4b4b4,
Te6edf3close_fdsTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3envTff7b72=Tff7b72selfTff7b72.Td2a8ff_build_envTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffcloseTb4b4b4(Te6edf3master_fdTb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffcloseTb4b4b4(Te6edf3slave_fdTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_master_fd Tff7b72= Tff7b72None
Tff7b72raise
Tff7b72finallyTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffcloseTb4b4b4(Te6edf3slave_fdTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_master_fd Tff7b72= Te6edf3master_fd

Tff7b72def Td2a8ff_start_with_pipeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3commandTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_master_fd Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_process Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffPopenTb4b4b4( T8b949e# noqa: S603
Te6edf3commandTb4b4b4,
Te6edf3stdinTff7b72=Te6edf3subprocessTff7b72.Td2a8ffPIPETb4b4b4,
Te6edf3stdoutTff7b72=Te6edf3subprocessTff7b72.Td2a8ffPIPETb4b4b4,
Te6edf3stderrTff7b72=Te6edf3subprocessTff7b72.Td2a8ffSTDOUTTb4b4b4,
Te6edf3bufsizeTff7b72=T79c0ff0Tb4b4b4,
Te6edf3envTff7b72=Tff7b72selfTff7b72.Td2a8ff_build_envTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffstopTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3process Tff7b72= Tff7b72selfTff7b72.Td2a8ff_process
Tff7b72selfTff7b72.Td2a8ff_stop_requested Tff7b72= Tff7b72True
Tff7b72if Te6edf3process Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72== Tff7b72selfTff7b72.Td2a8ffSTATUS_RUNNINGTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTATUS_STOPPED
Tff7b72selfTff7b72.Td2a8ffpid Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3processTff7b72.Td2a8ffterminateTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3processTff7b72.Td2a8ffwaitTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff2.5Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3processTff7b72.Td2a8ffkillTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3processTff7b72.Td2a8ffwaitTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff1.0Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_process Tff7b72is Te6edf3processTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflast_exit_code Tff7b72= Te6edf3processTff7b72.Td2a8ffpollTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffpid Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_process Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTATUS_STOPPED
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ff_on_session_changeTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72def Td2a8ffresizeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rowsTb4b4b4, Te6edf3colsTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3rows Tff7b72= Tffa657maxTb4b4b4(T79c0ff1Tb4b4b4, Tffa657intTb4b4b4(Te6edf3rowsTb4b4b4)Tb4b4b4)
Te6edf3cols Tff7b72= Tffa657maxTb4b4b4(T79c0ff1Tb4b4b4, Tffa657intTb4b4b4(Te6edf3colsTb4b4b4)Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffrows and cols must be integersTa5d6ff"Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_rows Tff7b72= Te6edf3rows
Tff7b72selfTff7b72.Td2a8ff_cols Tff7b72= Te6edf3cols
Te6edf3fd Tff7b72= Tff7b72selfTff7b72.Td2a8ff_master_fd
Tff7b72if Te6edf3fd Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_set_winsizeTb4b4b4(Te6edf3fdTb4b4b4, Te6edf3rowsTb4b4b4, Te6edf3colsTb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72FalseTb4b4b4)

Tff7b72def Td2a8ffsend_inputTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3textTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3textTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffInput must be a stringTa5d6ff"Tb4b4b4)
Te6edf3data Tff7b72= Te6edf3textTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3process Tff7b72= Tff7b72selfTff7b72.Td2a8ff_process
Tff7b72if Te6edf3process Tff7b72is Tff7b72None Tff7b72or Te6edf3processTff7b72.Td2a8ffpollTb4b4b4(Tb4b4b4) Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession is not runningTa5d6ff"Tb4b4b4)
Te6edf3fd Tff7b72= Tff7b72selfTff7b72.Td2a8ff_master_fd
Tff7b72if Te6edf3fd Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3osTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3fdTb4b4b4, Te6edf3dataTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3stdin Tff7b72= Te6edf3processTff7b72.Td2a8ffstdin
Tff7b72if Te6edf3stdin Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession stdin is unavailableTa5d6ff"Tb4b4b4)
Te6edf3stdinTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3dataTb4b4b4)
Te6edf3stdinTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72FalseTb4b4b4)

Tff7b72def Td2a8ff_reader_loopTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3process Tff7b72= Tff7b72selfTff7b72.Td2a8ff_process
Te6edf3master_fd Tff7b72= Tff7b72selfTff7b72.Td2a8ff_master_fd
Te6edf3fd Tff7b72= Te6edf3master_fd
Tff7b72if Te6edf3fd Tff7b72is Tff7b72None Tff7b72and Te6edf3process Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3processTff7b72.Td2a8ffstdout Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3fd Tff7b72= Te6edf3processTff7b72.Td2a8ffstdoutTff7b72.Td2a8fffilenoTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3process Tff7b72is Tff7b72None Tff7b72or Te6edf3fd Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Tff7b72while Tff7b72TrueTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3chunk Tff7b72= Te6edf3osTff7b72.Td2a8ffreadTb4b4b4(Te6edf3fdTb4b4b4, T79c0ff4096Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
T8b949e# A closed pty slave surfaces as EIO once the child exits.
Tff7b72return
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Te6edf3chunkTb4b4b4:
Tff7b72return
Te6edf3text Tff7b72= Te6edf3chunkTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Te6edf3output_chunk Tff7b72= Tff7b72selfTff7b72.Td2a8ffappend_outputTb4b4b4(Te6edf3textTb4b4b4)
Tff7b72if Te6edf3output_chunk Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ff_on_session_outputTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3output_chunkTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_persist_throttledTb4b4b4(Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3master_fd Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_master_fd Tff7b72== Te6edf3master_fdTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_master_fd Tff7b72= Tff7b72None
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffcloseTb4b4b4(Te6edf3master_fdTb4b4b4)

Tff7b72def Td2a8ff_persist_throttledTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Persist session state at most a few times per second.

Interactive sessions produce many small output chunks; saving the
whole store on every chunk would thrash the disk.
"""
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3now Tff7b72- Tff7b72selfTff7b72.Td2a8ff_last_persist Tff7b72< T79c0ff1.5Tb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_last_persist Tff7b72= Te6edf3now
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ff_waiter_loopTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3processTb4b4b4)Tb4b4b4:
T8b949e"""Wait for process and update status only if it is still current.

The process is passed in so a later restart cannot be clobbered by an
older waiter finishing after a new session process was started.
"""
Tff7b72if Te6edf3process Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return

Te6edf3exit_code Tff7b72= Te6edf3processTff7b72.Td2a8ffwaitTb4b4b4(Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_process Tff7b72is Tff7b72not Te6edf3processTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8fflast_exit_code Tff7b72= Te6edf3exit_code
Tff7b72selfTff7b72.Td2a8ffpid Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_process Tff7b72= Tff7b72None
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_stop_requestedTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tff7b72selfTff7b72.Td2a8ffSTATUS_STOPPED
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstatus Tff7b72= Tb4b4b4(
Tff7b72selfTff7b72.Td2a8ffSTATUS_FAILED Tff7b72if Te6edf3exit_code Tff7b72!= T79c0ff0 Tff7b72else Tff7b72selfTff7b72.Td2a8ffSTATUS_STOPPED
Tb4b4b4)
Tff7b72if Te6edf3exit_code Tff7b72!= T79c0ff0 Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8fflast_errorTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffrnsh exited with code Tffd700{Te6edf3exit_codeTffd700}Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ffupdated_at Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ff_on_session_changeTb4b4b4(Tff7b72selfTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmanagerTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffshutdownTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstopTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffto_storeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3data Tff7b72= Tff7b72selfTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72TrueTb4b4b4, Te6edf3output_tail_sizeTff7b72=T79c0ff400Tb4b4b4)
Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ffcreated_at
Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ffupdated_at
Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ffstatus
Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6fflisten_addressTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8fflisten_address
Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffrowsTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ff_rows
Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffcolsTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ff_cols
Tff7b72return Te6edf3data


Tff7b72class T56d364RNSHManagerTb4b4b4:
T8b949e"""Manage multiple rnsh sessions and persisted state."""

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3storage_dirTb4b4b4, Te6edf3reticulum_config_dirTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3storage_dir
Tff7b72selfTff7b72.Td2a8ffreticulum_config_dir Tff7b72= Tb4b4b4(
Te6edf3reticulum_config_dirTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3reticulum_config_dirTb4b4b4, Tffa657strTb4b4b4)
Tff7b72else Ta5d6ff"Ta5d6ff"
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sessions Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_change_callback Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_output_callback Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_lock Tff7b72= Te6edf3threadingTff7b72.Td2a8ffRLockTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffset_change_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_change_callback Tff7b72= Te6edf3callback

Tff7b72def Td2a8ffset_output_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_output_callback Tff7b72= Te6edf3callback

Tff7b72def Td2a8ff_store_pathTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Ta5d6ff"Ta5d6ffrnsh_sessions.jsonTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffloadTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_store_pathTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadTb4b4b4(Te6edf3handleTb4b4b4)
Te6edf3sessions Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsessionsTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3sessionsTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_sessions Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72for Te6edf3item Tff7b72in Te6edf3sessionsTb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3session_id Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3session_idTb4b4b4, Tffa657strTb4b4b4) Tff7b72or Tff7b72not Te6edf3session_idTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3session Tff7b72= Te6edf3RNSHSessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4, Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3itemTb4b4b4)
Te6edf3sessionTff7b72.Td2a8ffcreated_at Tff7b72= Tffa657floatTb4b4b4(Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3sessionTff7b72.Td2a8ffcreated_atTb4b4b4)
Te6edf3sessionTff7b72.Td2a8ffupdated_at Tff7b72= Tffa657floatTb4b4b4(Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3sessionTff7b72.Td2a8ffupdated_atTb4b4b4)
Te6edf3sessionTff7b72.Td2a8ffstatus Tff7b72= Te6edf3RNSHSessionTff7b72.Td2a8ffSTATUS_STOPPED
Te6edf3sessionTff7b72.Td2a8ffpid Tff7b72= Tff7b72None
Te6edf3sessionTff7b72.Td2a8fflast_exit_code Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_exit_codeTa5d6ff"Tb4b4b4)
Te6edf3sessionTff7b72.Td2a8fflast_error Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_errorTa5d6ff"Tb4b4b4)
Te6edf3sessionTff7b72.Td2a8fflast_command Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflast_commandTa5d6ff"Tb4b4b4)
Te6edf3stored_address Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflisten_addressTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3stored_addressTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Te6edf3stored_addressTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3sessionTff7b72.Td2a8fflisten_address Tff7b72= Te6edf3stored_addressTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3sessionTff7b72.Td2a8ff_output_seq Tff7b72= Tffa657intTb4b4b4(Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffoutput_seqTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3sessionTff7b72.Td2a8ff_output_seqTb4b4b4)
Te6edf3stored_chunks Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffoutput_chunksTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3stored_chunksTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Te6edf3sessionTff7b72.Td2a8ff_output_chunksTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Te6edf3sessionTff7b72.Td2a8ff_output_text Tff7b72= Ta5d6ff"Ta5d6ff"
Tff7b72for Te6edf3chunk Tff7b72in Te6edf3stored_chunksTb4b4b4:
Tff7b72if Tb4b4b4(
Tffa657isinstanceTb4b4b4(Te6edf3chunkTb4b4b4, Tffa657dictTb4b4b4)
Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3chunkTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4)Tb4b4b4, Tffa657intTb4b4b4)
Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3chunkTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4)Tb4b4b4, Tffa657strTb4b4b4)
Tb4b4b4)Tb4b4b4:
Te6edf3sessionTff7b72.Td2a8ff_output_chunksTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4: Te6edf3chunkTb4b4b4[Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4: Te6edf3chunkTb4b4b4[Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6fftsTa5d6ff"Tb4b4b4: Tffa657floatTb4b4b4(Te6edf3chunkTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftsTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3sessionTff7b72.Td2a8ff_output_text Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(
Te6edf3cTb4b4b4[Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4] Tff7b72for Te6edf3c Tff7b72in Te6edf3sessionTff7b72.Td2a8ff_output_chunks
Tb4b4b4)
Tff7b72if Te6edf3sessionTff7b72.Td2a8ff_output_chunksTb4b4b4:
Te6edf3sessionTff7b72.Td2a8ff_output_seq Tff7b72= Tffa657maxTb4b4b4(
Te6edf3sessionTff7b72.Td2a8ff_output_seqTb4b4b4,
Te6edf3sessionTff7b72.Td2a8ff_output_chunksTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffseqTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sessionsTb4b4b4[Te6edf3session_idTb4b4b4] Tff7b72= Te6edf3session

Tff7b72def Td2a8ffsaveTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3payload Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffsessionsTa5d6ff"Tb4b4b4: Tb4b4b4[Te6edf3sessionTff7b72.Td2a8ffto_storeTb4b4b4(Tb4b4b4) Tff7b72for Te6edf3session Tff7b72in Tff7b72selfTff7b72.Td2a8ff_sessionsTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4]Tb4b4b4,
Tb4b4b4}
Te6edf3path Tff7b72= Tff7b72selfTff7b72.Td2a8ff_store_pathTb4b4b4(Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3pathTb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3tmp_path Tff7b72= Ta5d6fffTa5d6ff"Tffd700{Te6edf3pathTffd700}Ta5d6ff.tmpTa5d6ff"
Tff7b72with Tffa657openTb4b4b4(Te6edf3tmp_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3jsonTff7b72.Td2a8ffdumpTb4b4b4(Te6edf3payloadTb4b4b4, Te6edf3handleTb4b4b4, Te6edf3ensure_asciiTff7b72=Tff7b72FalseTb4b4b4, Te6edf3indentTff7b72=T79c0ff2Tb4b4b4)
Te6edf3handleTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8fffsyncTb4b4b4(Te6edf3handleTff7b72.Td2a8fffilenoTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffreplaceTb4b4b4(Te6edf3tmp_pathTb4b4b4, Te6edf3pathTb4b4b4)

Tff7b72def Td2a8fflist_sessionsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3sessions Tff7b72= Tb4b4b4[
Te6edf3sessionTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72TrueTb4b4b4, Te6edf3output_tail_sizeTff7b72=T79c0ff400Tb4b4b4)
Tff7b72for Te6edf3session Tff7b72in Tff7b72selfTff7b72.Td2a8ff_sessionsTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)
Tb4b4b4]
Te6edf3sessionsTff7b72.Td2a8ffsortTb4b4b4(Te6edf3keyTff7b72=Tff7b72lambda Te6edf3itemTb4b4b4: Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffupdated_atTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4, Te6edf3reverseTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffsessionsTa5d6ff"Tb4b4b4: Te6edf3sessionsTb4b4b4}

Tff7b72def Td2a8fffind_sessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_sessionsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3session_idTb4b4b4)

Tff7b72def Td2a8ffcreate_sessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3configTb4b4b4)Tb4b4b4:
Te6edf3session_id Tff7b72= Te6edf3uuidTff7b72.Td2a8ffuuid4Tb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffhex
Te6edf3session Tff7b72= Te6edf3RNSHSessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4, Te6edf3config Tff7b72or Tb4b4b4{Tb4b4b4}Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_sessionsTb4b4b4[Te6edf3session_idTb4b4b4] Tff7b72= Te6edf3session
Tff7b72selfTff7b72.Td2a8ff_on_session_changeTb4b4b4(Te6edf3sessionTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3session

Tff7b72def Td2a8ffremove_sessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3session Tff7b72= Tff7b72selfTff7b72.Td2a8ff_sessionsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3session_idTb4b4b4)
Tff7b72if Te6edf3session Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession not foundTa5d6ff"Tb4b4b4)
Te6edf3sessionTff7b72.Td2a8ffshutdownTb4b4b4(Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_sessionsTff7b72.Td2a8ffpopTb4b4b4(Te6edf3session_idTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72True

Tff7b72def Td2a8ffstart_sessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4)Tb4b4b4:
Te6edf3session Tff7b72= Tff7b72selfTff7b72.Td2a8fffind_sessionTb4b4b4(Te6edf3session_idTb4b4b4)
Tff7b72if Te6edf3session Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession not foundTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3sessionTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffstop_sessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4)Tb4b4b4:
Te6edf3session Tff7b72= Tff7b72selfTff7b72.Td2a8fffind_sessionTb4b4b4(Te6edf3session_idTb4b4b4)
Tff7b72if Te6edf3session Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession not foundTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3sessionTff7b72.Td2a8ffstopTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffsend_inputTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4, Te6edf3textTb4b4b4)Tb4b4b4:
Te6edf3session Tff7b72= Tff7b72selfTff7b72.Td2a8fffind_sessionTb4b4b4(Te6edf3session_idTb4b4b4)
Tff7b72if Te6edf3session Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession not foundTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3sessionTff7b72.Td2a8ffsend_inputTb4b4b4(Te6edf3textTb4b4b4)

Tff7b72def Td2a8ffresize_sessionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4, Te6edf3rowsTb4b4b4, Te6edf3colsTb4b4b4)Tb4b4b4:
Te6edf3session Tff7b72= Tff7b72selfTff7b72.Td2a8fffind_sessionTb4b4b4(Te6edf3session_idTb4b4b4)
Tff7b72if Te6edf3session Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession not foundTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3sessionTff7b72.Td2a8ffresizeTb4b4b4(Te6edf3rowsTb4b4b4, Te6edf3colsTb4b4b4)

Tff7b72def Td2a8ffoutput_sinceTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4, Te6edf3cursorTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4:
Te6edf3session Tff7b72= Tff7b72selfTff7b72.Td2a8fffind_sessionTb4b4b4(Te6edf3session_idTb4b4b4)
Tff7b72if Te6edf3session Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession not foundTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3cursor Tff7b72= Tffa657intTb4b4b4(Te6edf3cursorTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3cursor Tff7b72= T79c0ff0
Tff7b72return Te6edf3sessionTff7b72.Td2a8ffoutput_sinceTb4b4b4(Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3cursorTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffclear_outputTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3session_idTb4b4b4)Tb4b4b4:
Te6edf3session Tff7b72= Tff7b72selfTff7b72.Td2a8fffind_sessionTb4b4b4(Te6edf3session_idTb4b4b4)
Tff7b72if Te6edf3session Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffSession not foundTa5d6ff"Tb4b4b4)
Te6edf3sessionTff7b72.Td2a8ffclear_outputTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3sessionTff7b72.Td2a8ffto_dictTb4b4b4(Te6edf3include_output_tailTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72def Td2a8ffshutdownTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3sessions Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_sessionsTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3session Tff7b72in Te6edf3sessionsTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3sessionTff7b72.Td2a8ffshutdownTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ff_on_session_changeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sessionTb4b4b4)Tb4b4b4:
Te6edf3callback Tff7b72= Tff7b72selfTff7b72.Td2a8ff_change_callback
Tff7b72if Te6edf3callback Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3callbackTb4b4b4(Te6edf3sessionTb4b4b4)

Tff7b72def Td2a8ff_on_session_outputTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sessionTb4b4b4, Te6edf3chunkTb4b4b4)Tb4b4b4:
Te6edf3callback Tff7b72= Tff7b72selfTff7b72.Td2a8ff_output_callback
Tff7b72if Te6edf3callback Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3callbackTb4b4b4(Te6edf3sessionTb4b4b4, Te6edf3chunkTb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────